<template>
  <div>
    <QuillEditor theme="snow" :toolbar="toolbarOptions" @selectionChange="selectionChange" ref="quill"/>
    <div class="float-container" :style="{top: (mouseY_ + 10) + 'px', left: mouseX_ + 'px', zIndex: 10}" v-show="showFloatingBox" ref="floatBox">
      <FloatBox v-if="showFloatingBox" @insert="insert" @replace="replace" :selectedContent="selectedContent"/>
    </div>
  </div>
</template>

<script setup>
import {QuillEditor} from '@vueup/vue-quill'
import HTMLtoDOCX from 'html-to-docx'
import {saveAs} from 'file-saver'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import {nextTick, onBeforeUnmount, onMounted, ref, watch} from 'vue'
import {storeToRefs} from 'pinia'
import {useStore} from '../store/index.js'
import FloatBox from './FloatBox.vue'

const store = useStore()
const { addFile, fileHtml, newFileStatus, exportAsDocxStatus, fileName, currentDocId, openFileStatus } = storeToRefs(store)
onMounted(()=>{
  let previousElement = document.querySelector('.ql-toolbar.ql-snow');
  let currentElement = document.querySelector('.ql-container.ql-snow');
  let previousElementHeight = previousElement.offsetHeight;
  currentElement.style.height = 'calc(100% - ' + previousElementHeight + 'px)';
})
let toolbarOptions = [
  [{ 'header': [1, 2, 3, 4, 5, 6, false] },{ 'size': ['small', false, 'large', 'huge'] },'bold', 'italic', 'underline',
    'strike',"image", { 'align': [] }, { 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' },
    { 'color': [] }, { 'background': [] }, 'clean'
  ]
]
const quill = ref(null)
watch(addFile,()=>{
  if(addFile.value){
    quill.value.setHTML(fileHtml.value)
    addFile.value = false
  }
})
const mouseUped = ref(false)
function selectionChange(e){
  if(e.range){
    if(!!e.range.length){
      // const tmp = quill.value.getContents(e.range.index, e.range.length).ops
      // let tmp_str = ''
      // tmp.forEach(item => {
      //   if(typeof item.insert === "string") tmp_str += item.insert
      // })
      // selectedContent.value = tmp_str
      selectedContent.value = quill.value.getText(e.range.index, e.range.length)
      setTimeout(()=>{
        if(mouseUped.value){
          mouseX_.value = mouseX.value
          mouseY_.value = mouseY.value
          showFloatingBox.value = true
        }
      },10)
    }else{
      showFloatingBox.value = false
    }
  }
}
const showFloatingBox = ref(false)
const mouseDownFlag = ref(false)
const mouseX = ref(0)
const mouseY = ref(0)
const mouseX_ = ref(0)
const mouseY_ = ref(0)
const floatBox = ref(null)
const mouseMoveHandler = (e) => {
  if(!showFloatingBox.value){
    mouseX.value = e.clientX;
    mouseY.value = e.clientY;
  }
}
const mouseDownHandler = (e) => {
  mouseDownFlag.value = true
  const width = floatBox.value.offsetWidth
  const height = floatBox.value.offsetHeight
  if(((width + mouseX_.value < e.clientX)||(mouseX_.value > e.clientX))||((height + mouseY_.value + 10 < e.clientY)||(mouseY_.value +10 > e.clientY))){
    showFloatingBox.value = false
  }
};
const mouseUpHandler = (e) => {
  mouseDownFlag.value = false
  mouseUped.value = true
  setTimeout(()=>{mouseUped.value = false},50)
};
const keyDownHandler = (event) => {
  switch (event.keyCode) {
    case 83: {
      if (event.ctrlKey && event.code === 'KeyS') {
        event.preventDefault()
        event.returnValue = false
        saveDoc()
      }
      break
    }
  }
}
function saveDoc() {
  const doc = quill.value.getHTML();
  let docs = localStorage.getItem('docs');
  if (!!docs) {
    docs = JSON.parse(docs)
    docs[currentDocId.value] = {
      id: currentDocId.value,
      name: fileName.value,
      saveTime: new Date().getTime(),
      content: doc
    }
  }else {
    docs = {
      [currentDocId.value]: {
        id: currentDocId.value,
        name: fileName.value,
        saveTime: new Date().getTime(),
        content: doc
      }
    }
  }
  localStorage.setItem('docs', JSON.stringify(docs))
  console.log(docs)
  ElMessage({
    message: '保存成功',
    type: 'success',
  })
}
onMounted(()=>{
  floatBox.value.addEventListener('mousedown', function(event) {
    event.preventDefault();
  });
  window.addEventListener('mousemove', mouseMoveHandler)
  window.addEventListener('mousedown', mouseDownHandler)
  window.addEventListener('mouseup', mouseUpHandler)
  window.addEventListener('keydown', keyDownHandler)
  titleConfig.forEach((item) => {
    const tip = document.querySelector(item.Choice);
    const toolBar = document.querySelector('.ql-toolbar');
    if (!tip) return;
    tip.addEventListener('mouseover', showTooltip);
    tip.addEventListener('mouseout', hideTooltip);
    const picker = tip.querySelector('.ql-picker-options')
    function showTooltip(event) {
      let target = event.target;
      if (!!picker&&(target === picker || picker.contains(target))) {
        hideTooltip();
      }else {
        const tooltip = createTooltip(item.text);
        toolBar.appendChild(tooltip);
      }
    }
    function hideTooltip() {
      const tooltip = toolBar.querySelector('.tooltip-container');
      if (tooltip) tooltip.remove();
    }
    function createTooltip(text) {
      const tooltip = document.createElement('div');
      tooltip.textContent = text;
      tooltip.classList.add('tooltip-container');
      tooltip.style.width = text.length + 1 + 'em';
      tooltip.style.left = tip.offsetLeft + 'px'
      return tooltip;
    }
  });
})
onBeforeUnmount(()=>{
  window.removeEventListener('mousemove', mouseMoveHandler)
  window.removeEventListener('mousedown', mouseDownHandler)
  window.removeEventListener('mouseup', mouseUpHandler)
  window.removeEventListener('keydown', keyDownHandler)
})
const selectedContent = ref('')
watch(newFileStatus,()=>{
  if(newFileStatus.value) {
    quill.value.setText('')
    newFileStatus.value = false
  }
})
watch(exportAsDocxStatus,async () => {
  if (exportAsDocxStatus.value) {
    const htmlString = quill.value.getHTML()
    const fileBuffer = await HTMLtoDOCX(htmlString)
    saveAs(fileBuffer, `${fileName.value?fileName.value:'无标题'}.docx`);
    exportAsDocxStatus.value = false
  }
})
const titleConfig = [
  { Choice: '.ql-bold', text: '加粗' },
  { Choice: '.ql-header', text: '文本类型' },
  { Choice: '.ql-size', text: '字体大小' },
  { Choice: '.ql-italic', text: '斜体' },
  { Choice: '.ql-underline', text: '下划线' },
  { Choice: '.ql-strike', text: '删除线' },
  { Choice: '.ql-image', text: '插入图片' },
  { Choice: '.ql-align', text: '文本对齐方式' },
  { Choice: '.ql-list[value="ordered"]', text: '编号列表' },
  { Choice: '.ql-list[value="bullet"]', text: '项目列表' },
  { Choice: '.ql-indent[value="-1"]', text: '向左缩进' },
  { Choice: '.ql-indent[value="+1"]', text: '向右缩进' },
  { Choice: '.ql-color', text: '字体颜色' },
  { Choice: '.ql-background', text: '背景颜色' },
  { Choice: '.ql-clean', text: '清除字体格式' },
]
watch(()=>{return openFileStatus.value.status}, () => {
  if(openFileStatus.value.status){
    quill.value.setHTML(openFileStatus.value.fileHtml)
    currentDocId.value = openFileStatus.value.id
    fileName.value = openFileStatus.value.fileName
    openFileStatus.value = {
      status: false,
      id: '',
      fileHtml: '',
      fileName: ''
    }
  }
},{immediate: true})
function replace(text) {
  const quillInstance = quill.value.getQuill();
  const range = quillInstance.getSelection();
  if (range) {
    const startPosition = range.index;
    quillInstance.deleteText(startPosition, range.length);
    quillInstance.insertText(startPosition, text);
    quillInstance.setSelection(startPosition, text.length);
  }
}

function insert(text){
  const range = quill.value.getQuill().getSelection();
  if (range) {
    const endPosition = range.index + range.length;
    quill.value.getQuill().insertText(endPosition, text);
  }
}
</script>

<style lang="scss">
.ql-toolbar.ql-snow {
  border-top: none;
}
.tooltip-container{
  background: white;
  position: absolute;
  bottom: -2em;
  border: 1px solid black;
  font-size: 0.9em;
  z-index: 2;
}
.float-container{
  position: absolute;
}
.ql-snow.ql-toolbar {
  position: relative;
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: '标题 1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: '标题 2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: '标题 3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: '标题 4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: '标题 5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: '标题 6';
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before, .ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: '正文';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
  content: '小';
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before, .ql-snow .ql-picker.ql-size .ql-picker-item::before {
 content: '中';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
  content: '大';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
 content: '超大';
}
.ql-snow .ql-picker {
  &.ql-size{
    width: 4em;
  }
  &.ql-header{
    width: 5em;
  }
}
</style>
